import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';

RemoteRtcVideoController useRemoteRtcVideoController() {
  return use(const _RemoteRtcVideoControllerHook());
}

class _RemoteRtcVideoControllerHook extends Hook<RemoteRtcVideoController> {
  const _RemoteRtcVideoControllerHook();

  @override
  HookState<RemoteRtcVideoController, Hook<RemoteRtcVideoController>> createState() {
    return _RemoteRtcVideoControllerHookState();
  }
}

typedef SetStateFunction = void Function(VoidCallback fn);

class _RemoteRtcVideoControllerHookState extends HookState<RemoteRtcVideoController, _RemoteRtcVideoControllerHook> {
  late RemoteRtcVideoController controller;
  
  @override
  void initHook() {
    super.initHook();
    controller = RemoteRtcVideoController();
    controller.setState = (VoidCallback fn) {
      setState(fn);
    };
    controller.init();
  }

  Future hangUp() async {
    controller.inCalling = false;
    controller.dispose();
  }

  @override
  RemoteRtcVideoController build(BuildContext context) {
    return controller;
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

class RemoteRtcVideoController {
  final renderer = RTCVideoRenderer();
  bool inCalling = false;
  MediaStream? stream;
  late SetStateFunction setState;
  List<MediaDeviceInfo>? mediaDevices;
  bool speakerphoneOn = false;

  init() async {
    await renderer.initialize();
    setState((){});
  }

  addTrack(s, track) {
    stream = s;
    renderer.srcObject = s;
    setSpeakerphoneOn(false);
    setState((){});
  }

  removeTrack(stream, track) {
    // TODO: removeTrack
  }
  
  dispose() async {
    await Future.forEach(stream?.getTracks() ?? [], (track) async {
      await track.stop();
    });
    stream?.dispose();
    renderer.srcObject = null;
    renderer.dispose();
  }

  Future<bool> toggleSpeakerphone() async {
    if (stream == null) return false;
    await Helper.setSpeakerphoneOn(!speakerphoneOn);
    speakerphoneOn = !speakerphoneOn;
    setState((){});
    return speakerphoneOn;
  }

  Future<bool> setSpeakerphoneOn(bool value) async {
    if (stream == null) return false;
    await Helper.setSpeakerphoneOn(value);
    speakerphoneOn = value;
    setState((){});
    return speakerphoneOn;
  }
}